import akka.actor.ActorRef
import akka.actor.ActorSystem
import com.typesafe.config.ConfigFactory
import io.netty.bootstrap.Bootstrap
import io.netty.channel.ChannelInitializer
import io.netty.channel.ChannelOption
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioSocketChannel
import io.netty.handler.codec.LengthFieldBasedFrameDecoder
import io.netty.handler.codec.LengthFieldPrepender
import xhhx.network.GoogleProtobufDecode
import xhhx.network.GoogleProtobufDecodeFromServer
import xhhx.network.GoogleProtobufEncode
import java.lang.Thread.sleep

fun main(args: Array<String>) {
    runRobot()
}

fun runRobot() {
    Boot().run()
}


const val ROBOT_COUNT = 200                  //机器人数量
const val PER_DELAY = 1000L                     //帧间隔
const val TARGET_IP = "192.168.0.122"             //目标IP
const val TARGET_PORT = 10111                   //目标端口
const val MAX_UPDATE_TIMES = 10                 //ai最多update次数,超过返回失败

const val MAX_FRAME_BYTES_LENGTH = 1024         //最大比特长度
const val LENGTH_FIELD = 2                      // 消息内容长度16位

val system = ActorSystem.create("ActorManager", ConfigFactory.load("ioBlock"))
lateinit var countRef: ActorRef
@Volatile
var isFinish = false

class Boot {
    private lateinit var b: Bootstrap;

    fun run() {
        initNetty()
        runRobot()
    }

    private fun initNetty() {
        b = Bootstrap()
        b.group(NioEventLoopGroup())
                .channel(NioSocketChannel::class.java)
                .option(ChannelOption.TCP_NODELAY, true)   // 要求低延迟，禁用nagle算法
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)   // 连接超时
                .option(ChannelOption.SO_SNDBUF, MAX_FRAME_BYTES_LENGTH) //sendBuff大小
                .option(ChannelOption.SO_RCVBUF, MAX_FRAME_BYTES_LENGTH) //receiveBuff大小
                .option(ChannelOption.SO_REUSEADDR, true) //  可以重复使用本地地址和端口
                .handler(object : ChannelInitializer<SocketChannel>() {
                    override fun initChannel(ch: SocketChannel) {
                        ch.pipeline()
                                .addLast(LengthFieldBasedFrameDecoder(MAX_FRAME_BYTES_LENGTH, 0, LENGTH_FIELD, 0, LENGTH_FIELD, true))
                                .addLast(GoogleProtobufDecodeFromServer())
                                .addLast(LengthFieldPrepender(LENGTH_FIELD, false))
                                .addLast(GoogleProtobufEncode())
                                .addLast(ClientHandler())
                    }
                })
    }

    private fun runRobot() {
        countRef = system.actorOf(CountActor.Props(ROBOT_COUNT, b))
        while (true && !isFinish) {
            countRef.tell(CountActor.RunMsg(), ActorRef.noSender())
            sleep(PER_DELAY)
        }

        System.out.println("Finish the RobotTask")
        system.terminate()
        b.config().group().shutdownGracefully()
    }
}